package edu.uoc.vmerinom.tfc.action;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.text.MessageFormat;
import java.util.List;

import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.contexts.ServletLifecycle;

import edu.uoc.vmerinom.tfc.domain.Perfil;
import edu.uoc.vmerinom.tfc.domain.Usuario;
import edu.uoc.vmerinom.tfc.service.PerfilesService;
import edu.uoc.vmerinom.tfc.service.UsuariosService;
import edu.uoc.vmerinom.tfc.support.Mail;
import edu.uoc.vmerinom.tfc.support.Message;
import edu.uoc.vmerinom.tfc.support.Utils;

/**
 * Manejador que contiene las acciones relacionadas con la gestión de usuarios
 * del portal.
 * 
 * @author Víctor Manuel Merino Martínez
 * 
 */
@Name("usuariosAction")
@Scope(ScopeType.CONVERSATION)
public class UsuariosAction implements Serializable {

	/**
	 * Default Serial Version ID.
	 */
	private static final long serialVersionUID = 1L;

	/**
	 * Servicio de usuarios.
	 */
	@In(create = true)
	UsuariosService usuariosService;

	/**
	 * Servicio de perfiles.
	 */
	@In(create = true)
	PerfilesService perfilesService;

	/**
	 * Listado completo de usuarios.
	 */
	List<Usuario> usuarios;
	/**
	 * Listado de perfiles activos.
	 */
	List<Perfil> perfiles;
	/**
	 * Usuario autenticado.
	 */
	@In(value = "usuario")
	Usuario login;
	/**
	 * Usuario seleccionado.
	 */
	Usuario usuario;
	/**
	 * Nueva contraseña.
	 */
	String pass;
	/**
	 * Antiguo usuario.
	 */
	String user;
	/**
	 * Lógico que indica si se mostrará el listado de usuarios.
	 */
	boolean listarUsuarios;
	/**
	 * Lógico que indica si se mostrará la edición de usuario.
	 */
	boolean editarUsuario;

	/**
	 * Carga los datos necesarios antes de mostrar la pantalla inicial.
	 */
	public void load() {
		usuarios = usuariosService.obtenerUsuarios(login.getId());
		listarUsuarios = true;
		editarUsuario = false;
	}

	/**
	 * Carga los datos para crear un nuevo usuario.
	 */
	public void nuevo() {
		usuario = new Usuario();
		editarUsuario = true;
		listarUsuarios = false;
		pass = "";
		user = "";
		if (login.getPerfil().isAdministrador()) {
			perfiles = perfilesService.obtenerPerfilesActivosAdmin();
		} else {
			perfiles = perfilesService.obtenerPerfilesActivos();
		}
	}

	/**
	 * Carga los datos para editar el usuario seleccionado.
	 */
	public void editar() {
		if (login.getPerfil().isAdministrador()) {
			perfiles = perfilesService.obtenerPerfilesActivosAdmin();
		} else {
			perfiles = perfilesService.obtenerPerfilesActivos();
		}
		editarUsuario = true;
		pass = "";
		user = usuario.getUser();
		listarUsuarios = false;
	}

	/**
	 * Carga los datos necesarios para volver a la pantalla del listado de
	 * usuarios.
	 */
	public void volver() {
		usuariosService.actualizarEstadoUsuario(usuario);
		editarUsuario = false;
		listarUsuarios = true;
	}

	/**
	 * Realiza comprobaciones y guarda los datos del usuario que se va a crear.
	 * 
	 * @throws IOException
	 *             Excepciones producidas por el fichero HTML del email
	 */
	public void guardarNuevoUsuario() throws IOException {
		if (validar()) {
			String password = "";
			pass = Utils.deleteBlankSpaces(pass);
			if (pass != null && !"".equals(pass)) {
				password = pass;
			} else {
				password = Utils.generateRandomString(8, true, true, true);
			}
			pass = "";

			user = usuario.getUser();
			String recipient = usuario.getEmail();
			String subject = Message.get("mail.registration.subject");
			Object[] params = new String[17];
			params[0] = MessageFormat.format(Message.get("mail.registration.welcome"), usuario.getUser());
			params[1] = Message.get("mail.registration.data.advice");
			params[2] = Message.get("mail.registration.data.id.number");
			params[3] = Message.get("mail.registration.data.name");
			params[4] = Message.get("mail.registration.data.surname");
			params[5] = Message.get("mail.registration.data.lastname");
			params[6] = Message.get("mail.registration.data.email");
			params[7] = Message.get("mail.registration.access.data");
			params[8] = Message.get("mail.registration.access.data.user");
			params[9] = Message.get("mail.registration.access.data.pass");
			params[10] = usuario.getDni();
			params[11] = usuario.getNombre();
			params[12] = usuario.getPrimerApellido();
			params[13] = usuario.getSegundoApellido();
			params[14] = usuario.getEmail();
			params[15] = usuario.getUser();
			params[16] = password;

			String mailFile = ServletLifecycle.getServletContext().getRealPath("/WEB-INF/classes/new-user.html");
			StringBuffer message = new StringBuffer();
			InputStream inputStream = new FileInputStream(new File(mailFile));
			int readed = inputStream.read();
			while (readed != -1) {
				message.append((char) readed);
				readed = inputStream.read();
			}
			usuario.setPass(Utils.encrypt(password, Utils.SHA1));
			usuariosService.insertarModificarUsuario(usuario);
			Mail.send(recipient, subject, MessageFormat.format(message.toString(), params));
			usuarios = usuariosService.obtenerUsuarios(login.getId());
			listarUsuarios = true;
			editarUsuario = false;
			Message.info("users.info.save.success");
		}
	}

	/**
	 * Guarda la edición del usuario seleccionado.
	 */
	public void guardarModificacionUsuario() {
		if (validar()) {
			boolean passChanged = false;
			boolean userChanged = false;
			pass = Utils.deleteBlankSpaces(pass);
			if (pass != null && !"".equals(pass)) {
				usuario.setPass(Utils.encrypt(pass, Utils.SHA1));
				passChanged = true;
			}
			if (!user.equals(usuario.getUser())) {
				userChanged = true;
			}

			if (passChanged || userChanged) {
				String recipient = usuario.getEmail();
				Object[] params = new String[2];
				params[0] = usuario.getUser();
				params[1] = pass;
				String subject = Message.get("mail.update.access.success.subject");
				String message = Message.get("mail.update.access.success.message");

				if (passChanged && !userChanged) {
					params = new String[1];
					params[0] = pass;
					subject = Message.get("mail.update.pass.success.subject");
					message = Message.get("mail.update.pass.success.message");
				} else if (!passChanged && userChanged) {
					params = new String[1];
					params[0] = usuario.getUser();
					subject = Message.get("mail.update.user.success.subject");
					message = Message.get("mail.update.user.success.message");
				}

				Mail.send(recipient, subject, MessageFormat.format(message, params));
			}

			usuariosService.insertarModificarUsuario(usuario);
			usuarios = usuariosService.obtenerUsuarios(login.getId());
			listarUsuarios = true;
			editarUsuario = false;
			Message.info("users.info.edit.success");
		}
	}

	/**
	 * Valida los campos del usuario.
	 * 
	 * @return <code>true</code> si la validación es correcta.
	 *         <code>false</code> si se ha producido algún error en la
	 *         validación: campos obligatorios no rellenos, formatos
	 *         incorrectos, etc.
	 */
	private boolean validar() {
		boolean result = true;
		Object[] params = null;
		if (usuario.getDni() == null) {
			Message.error("users.error.id.number.null");
			result = false;
		} else if ("".equals(Utils.deleteBlankSpaces(usuario.getDni()))) {
			Message.error("users.error.id.number.null");
			result = false;
		} else if (!Utils.validateDNI(usuario.getDni())) {
			Message.error("users.error.id.number.format");
			result = false;
		} else {
			final Usuario usu = usuariosService.obtenerUsuarioPorDNI(usuario.getDni(), usuario.getId());
			if (usu != null) {
				params = new String[1];
				params[0] = usuario.getDni();
				Message.error("users.error.id.number.repeated", params);
				result = false;
			}
		}

		if (usuario.getNombre() == null || "".equals(Utils.deleteBlankSpaces(usuario.getNombre()))) {
			Message.error("users.error.name.null");
			result = false;
		}
		if (usuario.getPrimerApellido() == null || "".equals(Utils.deleteBlankSpaces(usuario.getPrimerApellido()))) {
			Message.error("users.error.surname.null");
			result = false;
		}
		if (usuario.getEmail() == null || "".equals(Utils.deleteBlankSpaces(usuario.getEmail()))) {
			Message.error("users.error.email.null");
			result = false;
		} else if (!Utils.validateEmail(usuario.getEmail())) {
			Message.error("users.error.email.format");
			result = false;
		} else {
			final Usuario usu = usuariosService.obtenerUsuarioPorEmail(usuario.getEmail(), usuario.getId());
			if (usu != null) {
				params = new String[1];
				params[0] = usuario.getEmail();
				Message.error("users.error.email.repeated", params);
				result = false;
			}
		}
		if (usuario.getAlta() == null) {
			Message.error("users.error.registration.date.null");
			result = false;
		}
		if (usuario.getPerfil() == null) {
			Message.error("users.error.profile.null");
			result = false;
		}
		if (usuario.getUser() == null || "".equals(Utils.deleteBlankSpaces(usuario.getUser()))) {
			Message.error("users.error.username.null");
			result = false;
		} else {
			final Usuario usu = usuariosService.obtenerUsuario(usuario.getUser(), usuario.getId());
			if (usu != null) {
				params = new String[1];
				params[0] = usuario.getUser();
				Message.error("users.error.username.repeated", params);
				result = false;
			}
		}
		return result;
	}

	public List<Usuario> getUsuarios() {
		return usuarios;
	}

	public void setUsuarios(List<Usuario> usuarios) {
		this.usuarios = usuarios;
	}

	public boolean isListarUsuarios() {
		return listarUsuarios;
	}

	public void setListarUsuarios(boolean listarUsuarios) {
		this.listarUsuarios = listarUsuarios;
	}

	public boolean isEditarUsuario() {
		return editarUsuario;
	}

	public void setEditarUsuario(boolean editarUsuario) {
		this.editarUsuario = editarUsuario;
	}

	public Usuario getUsuario() {
		return usuario;
	}

	public void setUsuario(Usuario usuario) {
		this.usuario = usuario;
	}

	public List<Perfil> getPerfiles() {
		return perfiles;
	}

	public void setPerfiles(List<Perfil> perfiles) {
		this.perfiles = perfiles;
	}

	public String getPass() {
		return pass;
	}

	public void setPass(String pass) {
		this.pass = pass;
	}

}
